/*
---
description: OrderList

authors:
- Callum Jefferies (http://callumj.co.uk)

license: MIT-style

requires:
- core/1.4: '*'

provides:
- OrderList
...
*/

var OrderList = new Class({
	Implements: [Events, Options],

	options: {
		attrib: 'id',
		handle: null,
		onStart: function() {},
		onSort: function() {},
		onEnd: function() {},
	},

	initialize: function(list, options) {
		this.setOptions(options);
		this.list = $(list);
		this.move = this.move.bind(this);
		this.end = this.end.bind(this);

		var delegate = this.options.handle ?
			'mousedown:relay(li .' + this.options.handle + ')' :
			'mousedown:relay(li)';

		this.list.addEvent(delegate, this.start.bind(this));
	},

	start: function(e, target) {
		e.preventDefault();

		this.target_el = this.options.handle ? target.getParent('li') : target;
		this.start_key =
		this.end_key = this._get_current_key(this.target_el);

		window.addEvent('mousemove', this.move);
		window.addEvent('mouseup', this.end);

		this.fireEvent('start', this.target_el);
	},

	end: function(e) {
		window.removeEvent('mousemove', this.move);
		window.removeEvent('mouseup', this.end);

		if (this.start_key != this.end_key)
			this.fireEvent('end', [this.target_el, this._get_order()]);
	},

	move: function(e) {
		var prev = this.target_el.getPrevious('li'),
			next = this.target_el.getNext('li');

		this.end_key = this._get_current_key(this.target_el);

		if (prev && e.client.y <= prev.getCoordinates().bottom) {
			var current = this.target_el.dispose();
			current.inject(prev, 'before');
			this.fireEvent('sort', [current, this._get_order()]);
			return;
		}

		if (next && e.client.y >= next.getCoordinates().top) {
			var current = this.target_el.dispose();
			current.inject(next, 'after');
			this.fireEvent('sort', [current, this._get_order()]);
			return;
		}
	},

	_get_items: function() {
		return this.list.getElements('li');
	},

	_get_current_key: function(target) {
		return this._get_order().object[target.dataset[this.options.attrib]];
	},

	_get_order: function() {
		var order = {};

		this._get_items().each(function(el, index) {
			order[el.dataset[this.options.attrib]] = index;
		}.bind(this));

		return {
			'object': order,
			'json': JSON.encode(order),
			'query_string': Object.toQueryString(order),
		}
	}
});